"""
全局异常处理器
统一处理各种异常并返回标准响应格式
"""
# RequestHandler  ==== ApiResponse 
from fastapi import FastAPI, Request, HTTPException
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.responses import JSONResponse
from pydantic import ValidationError
import traceback
from app.schemas.base.error_code import ErrorCode

from app.utils.request import RequestHandler
from app.utils.app_log import logger


class BusinessError(Exception):
    """业务逻辑异常基类"""
    def __init__(self, error_code: ErrorCode, details: dict = None):
        self.message = error_code.message
        self.code = error_code.code  ## http code
        self.error_code = error_code.error_code  ## 业务错误码
        self.remarks = error_code.remarks
        self.details = details or {}
        super().__init__(self.message)



class GlobalExceptionHandler:
    """全局异常处理器类"""
    
    @staticmethod
    def setup_exception_handlers(app: FastAPI):
        """
        设置全局异常处理器
        
        Args:
            app: FastAPI应用实例
        """
        
        ## 第一 自己抛出的业务逻辑异常。
        @app.exception_handler(BusinessError)
        async def business_exception_handler(request: Request, exc: BusinessError):
            ## details 只做为日志打印
            logger.warning(
                f"Business Error: {exc.error_code} - {exc.message} | - {exc.details} "
                f"Path={request.url.path} | IP={request.client.host}"
            )
            
            return RequestHandler.error(
                code = exc.code,
                message = exc.message,
                data = None,
                remarks = exc.remarks  # ✅ 使用 ErrorCode 定义的 remarks
            )
        
        # 第2. 请求验证错误（用户输错参数）
        @app.exception_handler(RequestValidationError)
        async def validation_exception_handler(request: Request, exc: RequestValidationError):
            logger.warning(f"Validation Error: {exc.errors()}")
            
            error_details = [
                f"{' -> '.join(str(loc) for loc in e['loc'])}: {e['msg']}"
                for e in exc.errors()
            ]
            
            return RequestHandler.validation_error(
                message="请求数据验证失败",
                errors=error_details,
                remarks="请检查提交的数据格式和必填字段"
            )
        
         # 第3. HTTP 状态码异常（401/403/404/405 等）
        @app.exception_handler(HTTPException)
        async def http_exception_handler(request: Request, exc: HTTPException):
            """处理HTTPException"""
            logger.warning(f"HTTP Exception: {exc.status_code} - {exc.detail}|"
                           f"Path={request.url.path} | Method={request.method} | IP={request.client.host}")
            
            # 根据状态码返回相应的响应
            if exc.status_code == 401:
                return RequestHandler.unauthorized(
                    message=str(exc.detail),
                    remarks="请检查您的登录状态和权限"
                )
            elif exc.status_code == 403:
                return RequestHandler.forbidden(
                    message=str(exc.detail),
                    remarks="您没有权限访问此资源"
                )
            elif exc.status_code == 404:
                return RequestHandler.not_found(
                    message=str(exc.detail),
                    remarks="请检查请求的URL是否正确"
                )
            elif exc.status_code == 422:
                return RequestHandler.validation_error(
                    message=str(exc.detail),
                    remarks="请检查提交的数据格式"
                )
            else:
                return RequestHandler.error(
                    message=str(exc.detail),
                    code=exc.status_code,
                    remarks="请求处理失败"
                )
        
        @app.exception_handler(StarletteHTTPException)
        async def starlette_http_exception_handler(request: Request, exc: StarletteHTTPException):
            """处理Starlette HTTP异常"""
            logger.warning(f"Starlette HTTP Exception: {exc.status_code} - {exc.detail}")
            
            if exc.status_code == 404:
                return RequestHandler.not_found(
                    message="请求的资源不存在",
                    remarks=f"路径 {request.url.path} 未找到"
                )
            elif exc.status_code == 405:
                return RequestHandler.error(
                    message="请求方法不被允许",
                    code=405,
                    remarks=f"方法 {request.method} 不支持路径 {request.url.path}"
                )
            else:
                return RequestHandler.error(
                    message=str(exc.detail),
                    code=exc.status_code,
                    remarks="请求处理失败"
                )
        
        # 第4. 未捕获的异常（最后防线）
        @app.exception_handler(Exception)
        async def general_exception_handler(request: Request, exc: Exception):
            logger.error(f"Unhandled Exception: {type(exc).__name__}: {str(exc)}")
            logger.error(f"Traceback: {traceback.format_exc()}")
            
            return RequestHandler.server_error(
                message="服务器内部错误",
                remarks="系统出现异常，请联系管理员"
            )
        

def setup_global_exception_handler(app: FastAPI):
    """
    设置全局异常处理器的便捷函数
    
    Args:
        app: FastAPI应用实例
    """
    GlobalExceptionHandler.setup_exception_handlers(app)